using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace BitsOfStuff.GUI
{
    /// <summary>
    /// Virtual keyboard intended to be embedded within a window containing TextBox controls.
    /// The keyboard allows touch input to be captured while requiring no code binding.
    /// </summary>
    public partial class VirtualKeyboard
    {
        /// <summary> Dependency property for the IsShiftPressed property. </summary>
        public static readonly DependencyProperty IsShiftPressedProperty = DependencyProperty.Register(
            "IsShiftPressed", typeof(bool), typeof(VirtualKeyboard), new PropertyMetadata(false));

        /// <summary> Gets or sets whether the shift key is currently pressed on the keyboard. </summary>
        public bool IsShiftPressed
        {
            get { return (bool)this.GetValue(IsShiftPressedProperty); }
            set { this.SetValue(IsShiftPressedProperty, value); }
        }

        /// <summary> Dependency property for the IsCapsLockPressed property. </summary>
        public static readonly DependencyProperty IsCapsLockPressedProperty = DependencyProperty.Register(
            "IsCapsLockPressed", typeof(bool), typeof(VirtualKeyboard), new PropertyMetadata(false));

        /// <summary> Gets or sets whether the caps lock key is current pressed on the keyboard. </summary>
        public bool IsCapsLockPressed
        {
            get { return (bool)this.GetValue(IsCapsLockPressedProperty); }
            set { this.SetValue(IsCapsLockPressedProperty, value); }
        }

        /// <summary> Initializes a new instance of the VirtualKeyboard class. </summary>
        public VirtualKeyboard()
        {
            InitializeComponent();
        }

        /// <summary>
        /// Handles standard (letter/number) virtual keyboard presses.
        /// </summary>
        private void WriteText(object sender, RoutedEventArgs e)
        {
            // For all normal letters and numbers, we can just grab the letter that was on the key.
            string text = ((Button)sender).Content.ToString();

            if (this.IsShiftPressed)
            {
                // Unselect the shift key once a capital letter has been inserted.
                this.IsShiftPressed = false;
            }
            else if (this.IsCapsLockPressed == false)
            {
                text = text.ToLower();
            }

            var textEvent = new TextCompositionEventArgs(Keyboard.PrimaryDevice, new TextComposition(InputManager.Current, Keyboard.FocusedElement, text))
                                {
                                    RoutedEvent = TextInputEvent
                                };

            InputManager.Current.ProcessInput(textEvent);
        }

        /// <summary> Handles standard (letter/number) virtual keyboard presses.  </summary>
        /// <param name="sender"> Keyboard button sending the event. </param>
        /// <param name="e"> Event arguments. </param>
        private void PressSpecialKey(object sender, RoutedEventArgs e)
        {
            Key key = (Key)((Button)sender).Tag;

            KeyEventArgs keyEvent = new KeyEventArgs(Keyboard.PrimaryDevice, Keyboard.PrimaryDevice.ActiveSource, 0, key)
            {
                RoutedEvent = KeyDownEvent
            };

            InputManager.Current.ProcessInput(keyEvent);
        }

        /// <summary> Presses or depresses the shift key when caps lock is not pressed. </summary>
        /// <param name="sender"> Object sending the event. </param>
        /// <param name="e"> Event arguments. </param>
        private void PressShift(object sender, RoutedEventArgs e)
        {
            // No reason to change anything if caps is enabled.
            if (this.IsCapsLockPressed == false)
            {
                this.IsShiftPressed = !IsShiftPressed;
            }
        }

        /// <summary> Presses or depresses the caps lock key. </summary>
        /// <param name="sender"> Object sending the event. </param>
        /// <param name="e"> Event arguments. </param>
        private void PressCapsLock(object sender, RoutedEventArgs e)
        {
            this.IsCapsLockPressed = !IsCapsLockPressed;

            this.IsShiftPressed = false;
        }
    }
}